home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_500 / wiconify / wiconify-source.lzh / Source / wHandler.c < prev    next >
C/C++ Source or Header  |  1991-04-25  |  30KB  |  952 lines

  1. /*
  2.  *  WICONIFY    A utility that allows you to iconify any Intuition window
  3.  *              on any screen, and to open WB windows on any screen.
  4.  *
  5.  *  wHandler.c  The Input Handler and replacement routines for the
  6.  *              Intuition functions trapped by SetFunction().
  7.  *
  8.  *  Copyright 1990 by Davide P. Cervone, all rights reserved.
  9.  *  You may use this code, provided this copyright notice is kept intact.
  10.  */
  11.  
  12. #define INTUITION_PREFERENCES_H             /* don't need 'em */
  13. #include <intuition/intuitionbase.h>
  14. #include "wHandler.h"
  15. #include "wMenu.h"
  16. #include <libraries/dosextens.h> 
  17. #include <graphics/gfxbase.h>
  18.  
  19.  
  20. /*
  21.  *  The definition for wIconify BackDrop windows
  22.  *  (the IDCMPFlags are added later, since they share a UserPort)
  23.  */
  24. static struct NewWindow BDWindow =
  25. {
  26.    0,0, 0,0, -1,-1, NULL,
  27.    SIMPLE_REFRESH| NOCAREREFRESH| BACKDROP| BORDERLESS| REPORTMOUSE,
  28.    NULL, NULL, NULL, NULL, NULL, 20,20, -1,-1, WBENCHSCREEN
  29. };
  30.  
  31. extern struct wMenuItem OpenWindowMenu[];
  32.  
  33. /*
  34.  *  Tells whether a screen is iconified (i.e., pushed off the bottom)
  35.  */
  36. #define ISICONIFIED(s)  ((s)->TopEdge > GfxBase->NormalDisplayRows)
  37.  
  38.  
  39.  
  40. /*
  41.  *  CheckIconifiedScreen()
  42.  *
  43.  *  If the front screen is iconified, move it to the back.
  44.  *  If there is an active window
  45.  *    If its screen is iconified
  46.  *      Look for the next uniconified screen
  47.  *      (Start over from the front of the list if we hit the end)
  48.  *      If we found an uniconified screen and it has a window
  49.  *        Activate the window
  50.  *  (i.e, try to make sure that windows on iconified screens never become
  51.  *  active.  Give preference to forward screens rather than backward ones.
  52.  *  This may effect the use of some hot-key screen shufflers that activate
  53.  *  windows on the new front screen:  pushing screens to the back will
  54.  *  still work fine, but pulling the back one to the front will fail).
  55.  */
  56.  
  57. static void CheckIconifiedScreen()
  58. {
  59.    struct Screen *iScreen;
  60.    
  61.    Forbid();
  62.    iScreen = IntuitionBase->FirstScreen;
  63.    if (ISICONIFIED(iScreen)) ScreenToBack(iScreen);
  64.    if (IntuitionBase->ActiveWindow)
  65.    {
  66.       iScreen = IntuitionBase->ActiveWindow->WScreen;
  67.       if (ISICONIFIED(iScreen))
  68.       {
  69.          while (iScreen && ISICONIFIED(iScreen)) iScreen = iScreen->NextScreen;
  70.          if (iScreen == NULL)
  71.          {
  72.             iScreen = IntuitionBase->FirstScreen;
  73.             while (iScreen && ISICONIFIED(iScreen))
  74.                iScreen = iScreen->NextScreen;
  75.          }
  76.          if (iScreen && iScreen->FirstWindow)
  77.             ActivateWindow(iScreen->FirstWindow);
  78.       }
  79.    }
  80.    Permit();
  81. }
  82.  
  83.  
  84. /*
  85.  *  wHandler()
  86.  *
  87.  *  If we are in the process of ending, just return the list
  88.  *  Check for iconified screens
  89.  *  While there are events in the list
  90.  *    If they are mouse or key events
  91.  *      If the event matches the iconify-key specification (up or down)
  92.  *        If the event is the key or button up event
  93.  *          Get a new message to send to the wIconify process
  94.  *          Set up the values to pass to it
  95.  *          Send it to the handler process
  96.  *        Remove this event from the list
  97.  *        (ie, process key-up events, but just remove key-down events)
  98.  *      Otherwise, if the event matches the activation-key specification
  99.  *        If it's the key up event
  100.  *          Get the current active screen
  101.  *          Activate its wIconify window, if any
  102.  *        Remove this event from the list (as above)
  103.  *    If we are removing the event from the list, do so
  104.  *    Go on to the next event in the list
  105.  *  Return the (modified) list.
  106.  */
  107.  
  108. struct InputEvent *wHandler(EventList,data)
  109. struct InputEvent *EventList;
  110. APTR data;
  111. {
  112.    struct InputEvent **EventPtr = &EventList;
  113.    struct InputEvent *theEvent;
  114.    struct wIconMessage *theMessage;
  115.    WSCREEN *theScreen;
  116.    int RemoveEvent = FALSE;
  117.  
  118.  
  119.    if (EndSignal) return(EventList);
  120.  
  121.    CheckIconifiedScreen();
  122.    while (theEvent = *EventPtr)
  123.    {
  124.       if (theEvent->ie_Class == IECLASS_RAWMOUSE ||
  125.           theEvent->ie_Class == IECLASS_RAWKEY)
  126.       {
  127.          if ((theEvent->ie_Code | IECODE_UP_PREFIX) == IconifyKey &&
  128.             (theEvent->ie_Qualifier & (IconifyQuals | IconifyDisquals))
  129.                    == IconifyQuals)
  130.          {
  131.             if (theEvent->ie_Code == IconifyKey)
  132.             {
  133.                if (NEWSTRUCT(wIconMessage,theMessage))
  134.                {
  135.                   theMessage->Window = IntuitionBase->ActiveWindow;
  136.                   theMessage->Action = WI_ICONIFY;
  137.                   theMessage->Flags  = WI_NOREPLY;
  138.                   if ((theEvent->ie_Qualifier & IconifyChange) == IconifyChange)
  139.                      theMessage->Flags |= WI_CHANGE;
  140.                   theMessage->Message.mn_ReplyPort = NULL;
  141.                   theMessage->Message.mn_Length = sizeof(struct wIconMessage);
  142.                   PutMsg(wIconPort,theMessage);
  143.                }
  144.             }
  145.             RemoveEvent = TRUE;
  146.          } else if ((theEvent->ie_Code | IECODE_UP_PREFIX) == ActivateKey &&
  147.                    (theEvent->ie_Qualifier & ActivateQuals) == ActivateQuals) {
  148.             if (theEvent->ie_Code == ActivateKey)
  149.             {
  150.                Forbid();
  151.                theScreen = FindScreen(IntuitionBase->ActiveScreen);
  152.                if (theScreen && theScreen->BackDrop)
  153.                   ActivateWindow(theScreen->BackDrop);
  154.                Permit();
  155.             }
  156.             RemoveEvent = TRUE;
  157.          }
  158.       }
  159.       if (RemoveEvent)
  160.          *EventPtr = theEvent->ie_NextEvent;
  161.         else
  162.           EventPtr = &(theEvent->ie_NextEvent);
  163.       RemoveEvent = FALSE;
  164.    }
  165.    return(EventList);
  166. }
  167.  
  168.  
  169. #define TOUPPER(c)      (((c)>='a'&&(c)<='z')?(c)-'a'+'A':c)
  170.  
  171.  
  172. /*
  173.  *  PrefixMatch()
  174.  *
  175.  *  Case-insensitive prefix match.  The empty string will match NULL pointers
  176.  *  and empty strings, but are not considered prefixes to any string.
  177.  *
  178.  *  Return <0 if the first is smaller than the second,
  179.  *         =0 if the first is a prefix of the second,
  180.  *         >1 if the first is larger than the second.
  181.  */
  182.  
  183. int PrefixMatch(s1,s2)
  184. char *s1,*s2;
  185. {
  186.    int match = -1;
  187.    
  188.    if (*s1)
  189.    {
  190.       if (s2)
  191.       {
  192.          while (TOUPPER(*s1) == TOUPPER(*s2) && *s2 != 0) s1++,s2++;
  193.          if (*s1 == 0) match = 0; else match = *s1 - *s2;
  194.       } else match = 1;
  195.    } else if (s2 == NULL || *s2 == 0) match = 0;
  196.    return(match);
  197. }
  198.  
  199.  
  200. /*
  201.  *  GetScreen()
  202.  *
  203.  *  Find the screen where the window will open via the following rules:
  204.  *    If we are supposed to open on the active screen, get the active screen
  205.  *    Otherwise, if we are supposed to open on the current WB, get it
  206.  *    If we have found a screen
  207.  *       If the screen is the real WB, forget it (no changes needed)
  208.  *       If the screen is closing or iconified, forget it
  209.  *       If the screen we are opening on is not currently active
  210.  *  Get the actual screen pointer of the screen we are interested in
  211.  *  If it is not active, we should bring it to the front
  212.  *  return the WSCREEN we shoulod use (or NULL if no action)
  213.  */
  214.  
  215. static WSCREEN *GetScreen(BringToFront)
  216. int *BringToFront;
  217. {
  218.    WSCREEN *theScreen = NULL;
  219.    struct Screen *chkScreen = NULL;
  220.  
  221.    if (OpenWindowMenu[OW_ACTIVESCRN].Item.Flags & CHECKED)
  222.       theScreen = FindScreen(IntuitionBase->ActiveScreen); else
  223.    if (OpenWindowMenu[OW_CURRENTWB].Item.Flags & CHECKED)
  224.       theScreen = WBScreen;
  225.    if (theScreen)
  226.    {
  227.       if (theScreen == RealWB) theScreen = NULL; else
  228.       if ((theScreen->Flags & WI_CLOSING) ||
  229.           (theScreen->Icon.Icon.Flags & WI_ICONIFIED))
  230.               theScreen = NULL;
  231.    }
  232.    if (theScreen) chkScreen = theScreen->Screen;
  233.    else if (RealWB) chkScreen = RealWB->Screen;
  234.    *BringToFront = (chkScreen != IntuitionBase->ActiveScreen);
  235.    return(theScreen);
  236. }
  237.  
  238.  
  239. /*
  240.  *  CheckWindowSize()
  241.  *
  242.  *  If the window has a drag bar
  243.  *    Check if it fits on the screen; if not, move it to a better spot
  244.  *  If the window has a sizing gadget or accepts NEWSIZE messages
  245.  *    If the window doesn't fint on the screen, shrink it so that it does
  246.  *  Return an indication of whether the size was modified
  247.  */
  248.  
  249. static int CheckWindowSize(newWindow)
  250. struct NewWindow *newWindow;
  251. {
  252.    short x = newWindow->LeftEdge;
  253.    short y = newWindow->TopEdge;
  254.    short w = newWindow->Width;
  255.    short h = newWindow->Height;
  256.    short Sw = newWindow->Screen->Width;
  257.    short Sh = newWindow->Screen->Height;
  258.    int Sized = FALSE;
  259.    
  260.    if (newWindow->Flags & WINDOWDRAG)
  261.    {
  262.       if (x+w > Sw) x = newWindow->LeftEdge = (Sw > w)? Sw - w: 0;
  263.       if (y+h > Sh) y = newWindow->TopEdge  = (Sh > h)? Sh - h: 0;
  264.    }
  265.    if ((newWindow->Flags & WINDOWSIZING) || (newWindow->IDCMPFlags & NEWSIZE))
  266.    {
  267.       if (x < Sw && x+w > Sw) newWindow->Width  = Sw - x, Sized = TRUE;
  268.       if (y < Sh && y+h > Sh) newWindow->Height = Sh - y, Sized = TRUE;
  269.    }
  270.    return(Sized);
  271. }
  272.  
  273.  
  274. /*
  275.  *  cOpenWindow()
  276.  *
  277.  *  If we have a new window and we are not in the process of ending Iconify
  278.  *    Get the screen where we should open, and the bring-to-front flag
  279.  *    If we have a screen to open on, and the window was opening on the WB
  280.  *      Get a new wbWindow structure for it
  281.  *      Copy the NewWindow info so we can change it
  282.  *      Change the window specification so that it opens on the right screen
  283.  *      If we are allowed to resize the window, check if it needs it
  284.  *      Try to open the window
  285.  *      If successful
  286.  *        Link the window into the screen's list of foreign windows
  287.  *        Send a resize message if the window was sized
  288.  *      Otherwise
  289.  *        Free the allocated structure (we won't be needing it)
  290.  *    Otherwise (it's not a window we're supposed to change)
  291.  *    If the real WB screen is open and this window is the WB backdrop
  292.  *        window (ie, LoadWB is trying to start the WB)
  293.  *      Copy the NewWindow structure so we can "fix" it
  294.  *      Set the width to something smaller
  295.  *      Move the window to the right side of the screen
  296.  *      Make it a regular non-backdrop window with a border
  297.  *      Add the sizing, dragging and depth gadgets
  298.  *      Then open the window
  299.  *  If the window was not opened yet, open it as a normal window
  300.  *  If we are supposed to bring a screen to the front and the window
  301.  *    was actually opened, bring the screen to front
  302.  *  Return the pointer to the opened window
  303.  */
  304.  
  305. struct Window *cOpenWindow(newWindow)
  306. struct NewWindow *newWindow;
  307. {
  308.    struct Window *theWindow = NOWINDOW;
  309.    struct NewWindow tmpWindow;
  310.    WBWINDOW *WBWindow;
  311.    WSCREEN *theScreen = NULL;
  312.    int BringToFront = FALSE;
  313.    int Sized = FALSE;
  314.  
  315.    if (newWindow && EndSignal == 0)
  316.    {
  317.       Forbid();
  318.       theScreen = GetScreen(&BringToFront);
  319.       if (theScreen && (newWindow->Type & SCREENTYPE) == WBENCHSCREEN)
  320.       {
  321.          if (NEWSTRUCT(wbWindow,WBWindow))
  322.          {
  323.             tmpWindow = *newWindow;
  324.             tmpWindow.Screen = theScreen->Screen;
  325.             tmpWindow.Type = CUSTOMSCREEN;
  326.             if (OpenWindowMenu[OW_AUTORESIZE].Item.Flags & CHECKED)
  327.                Sized = CheckWindowSize(&tmpWindow);
  328.             theWindow = aOldOpenWindow(&tmpWindow);
  329.             if (theWindow)
  330.             {
  331.                WBWindow->Window = theWindow;
  332.                LinkWindow(WBWindow,theScreen);
  333.                if (Sized) SendIntuiMessage(NEWSIZE,theWindow);
  334.             } else {
  335.                FREESTRUCT(wbWindow,WBWindow);
  336.             }
  337.          }
  338.       } else if (RealWB && (newWindow->Flags & WBFLAGS) == WBFLAGS) {
  339.          tmpWindow = *newWindow;
  340.          tmpWindow.Width = WBWIDTH;
  341.          tmpWindow.LeftEdge = RealWB->Screen->Width - WBWIDTH;
  342.          tmpWindow.Flags &= ~(BORDERLESS | BACKDROP);
  343.          tmpWindow.Flags |= WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH;
  344.          theWindow = aOldOpenWindow(&tmpWindow);
  345.       }
  346.       Permit();
  347.    }
  348.    if (theWindow == NOWINDOW) theWindow = aOldOpenWindow(newWindow);
  349.    if (BringToFront && theWindow != NOWINDOW) ScreenToFront(theWindow->WScreen);
  350.    return(theWindow);
  351. }
  352.  
  353.  
  354. /*
  355.  *  ParentWindow()
  356.  *
  357.  *  Get the parent window of the current one
  358.  *  If it has one, then
  359.  *     Find its icon
  360.  *     While the window we are looking at is iconified
  361.  *       Go to its parent and get its icon
  362.  *  If we did not find a window, use the screen's backdrop window
  363.  *  Return the window that we found
  364.  */
  365.  
  366. static struct Window *ParentWindow(theWindow)
  367. struct Window *theWindow;
  368. {
  369.    WICONREF *theIcon;
  370.    WSCREEN *theScreen = NULL;
  371.    
  372.    theWindow = theWindow->Parent;
  373.    if (theWindow)
  374.    {
  375.       theIcon = FindIcon(theWindow,&theScreen);
  376.       while (theIcon && (theIcon->Icon.Flags & WI_ICONIFIED))
  377.       {
  378.          theWindow = theWindow->Parent;
  379.          theIcon = (theWindow)? FindIcon(theWindow,&theScreen): NULL;
  380.       }
  381.    }
  382.    if (theWindow == NULL && theScreen) theWindow = theScreen->BackDrop;
  383.    return(theWindow);
  384. }
  385.  
  386.  
  387. /*
  388.  *  FinishWindow()
  389.  *
  390.  *  Find the icon of the window that is closing
  391.  *  If it has one, tell the Iconify process to remove it
  392.  *  Find the wbWindow structure of this window (if any)
  393.  *  If it has one (ie, it is opened on a foreign screen)
  394.  *    Unlink the window from the screen
  395.  *    If it was the last one on the screen, let the Iconify process know
  396.  *      (it may want to update the menu to include CLOSESCREEN)
  397.  *    Free the window structure
  398.  *    If the Iconify process was waiting to end, let it try now
  399.  *  Find the (first non-iconified) parent of this window
  400.  *  Close the window
  401.  *  If the screen was waiting to close, signal it that it can
  402.  *  Of Iconify wants to hear about this window, signal it
  403.  *  If Intuition would attempt to activate an iconified window,
  404.  *    Activate the first non-iconified parent window
  405.  */
  406.  
  407. static void FinishWindow(oldWindow,RemoveWindow)
  408. struct Window *oldWindow;
  409. void (*RemoveWindow)();
  410. {
  411.    WBWINDOW *theWindow;
  412.    APTR  ScreenTask = NULL;
  413.    ULONG ScreenSignal;
  414.    ULONG IconSignal = 0;
  415.    WICONREF *theIcon;
  416.    WSCREEN *theScreen;
  417.    struct Window *Parent,*OldParent;
  418.  
  419.    Forbid();
  420.    theIcon = FindIcon(oldWindow,&theScreen);
  421.    if (theIcon) SendIconMessage(WI_REMOVEICON,NULL,theScreen,theIcon);
  422.    theWindow = FindWindow(oldWindow);
  423.    if (theWindow)
  424.    {
  425.       ScreenTask   = theWindow->Screen->CloseTask;
  426.       ScreenSignal = theWindow->Screen->CloseSignal;
  427.       UnLinkWindow(theWindow);
  428.       if (theWindow->Screen->Window == NULL) IconSignal = CloseSignal;
  429.       FREESTRUCT(wbWindow,theWindow);
  430.       IconSignal |= EndSignal;
  431.    }
  432.    Parent = ParentWindow(oldWindow); OldParent = oldWindow->Parent;
  433.    Permit();
  434.    (*RemoveWindow)(oldWindow);
  435.    if (ScreenTask) Signal(ScreenTask,ScreenSignal);
  436.    if (IconSignal) Signal(IconTask,IconSignal);
  437.    if (Parent && Parent != OldParent) ActivateWindow(Parent);
  438. }
  439.  
  440.  
  441. /*
  442.  *  cCloseWindow()
  443.  *
  444.  *  We are finished with this window; use the old CloseWindow() routine
  445.  *  to remove it from the screen.
  446.  */
  447.  
  448. void cCloseWindow(oldWindow)
  449. struct Window *oldWindow;
  450. {
  451.    extern void aOldCloseWindow();
  452.  
  453.    FinishWindow(oldWindow,&aOldCloseWindow);
  454. }
  455.  
  456.  
  457. /*
  458.  *  cOpenScreen()
  459.  *
  460.  *  If the screen was opened OK, and the Iconify process is not ending
  461.  *    Look through the ignore-screen list for this screen
  462.  *    If it does not appear in the list
  463.  *      Get a new Screen sctructure for this screen
  464.  *      Open a BackDrop window of the correct size on this screen
  465.  *      Set up the screen's icon
  466.  *      If the BackDrop window opened OK
  467.  *        Link the screen into the list
  468.  *        Set the new window as the current WB window
  469.  *       else
  470.  *        Free the structure, we won't be needing it
  471.  */
  472.  
  473. void cOpenScreen(newScreen)
  474. struct Screen *newScreen;
  475. {
  476.    WSCREEN *theScreen;
  477.    struct Ignore *igScreen = IgnoreScreen;
  478.    extern struct Window *OpenWindow();
  479.    extern struct Menu wMenu[];
  480.  
  481.    if (newScreen && EndSignal == 0)
  482.    {
  483.       while (igScreen && PrefixMatch(igScreen->Title,newScreen->DefaultTitle))
  484.          igScreen = igScreen->Next;
  485.       if (igScreen == NULL)
  486.       {
  487.          if (NEWSTRUCT(wScreen,theScreen))
  488.          {
  489.             theScreen->Screen = newScreen;
  490.             BDWindow.Screen = newScreen;
  491.             BDWindow.Type   = newScreen->Flags & SCREENTYPE;
  492.             BDWindow.Width  = newScreen->Width;
  493.             BDWindow.Height = newScreen->Height;
  494.             theScreen->BackDrop = OpenWindow(&BDWindow);
  495.             theScreen->Icon.Icon.Name  = newScreen->DefaultTitle;
  496.             theScreen->Icon.Icon.Flags = WI_SCREENICON| DefaultScreenFlags;
  497.             theScreen->Icon.Screen     = theScreen;
  498.             theScreen->Icon.Window     = theScreen->BackDrop;
  499.             if (theScreen->BackDrop)
  500.             {
  501.                LinkScreen(theScreen);
  502.                NewIconWindow(theScreen);
  503.             } else {
  504.                FREESTRUCT(wScreen,theScreen);
  505.             }
  506.          }
  507.       }
  508.    }
  509. }
  510.  
  511.  
  512. /*
  513.  *  cCloseScreen()
  514.  *
  515.  *  Look to see if the screen is in the list of screens with wIconify windows
  516.  *  If so,
  517.  *    Mark the screen as closing so we don't allow any more icons on it
  518.  *    If the screen is the current WB, clear the current WB
  519.  *    If the screen is the real WB screen (should never happen), forget it
  520.  *    Restore the screen's icon if it is iconified
  521.  *    Tell anyone who's interested that the screen is closing
  522.  *    Remove any icons we're allowed to remove
  523.  *    Wait for any foreign windows or other icons to be removed
  524.  *    If the current task is the wIconify handler process, unlink the screen
  525.  *    Otherwise send wIconify the message to remove the screen
  526.  *    Close the wIconify backdrop window
  527.  *    Close the screen itself and free the screen structure
  528.  *  Otherwise
  529.  *    Just close the screen
  530.  */
  531.  
  532. void cCloseScreen(oldScreen)
  533. struct Screen *oldScreen;
  534. {
  535.    WSCREEN *theScreen;
  536.  
  537.    Forbid();
  538.    theScreen = FindScreen(oldScreen);
  539.    if (theScreen)
  540.    {
  541.       theScreen->Flags |= WI_CLOSING;
  542.       if (theScreen == WBScreen) NewWBScreen(NULL);
  543.       if (theScreen == RealWB)   RealWB = NULL;
  544.       Permit();
  545.       Restore(&(theScreen->Icon),TRUE);
  546.       ReportMulti(WI_REPORTSCREENCLOSE,theScreen->Screen,theScreen);
  547.       RemoveAutoIcons(theScreen);
  548.       WaitForWindows(theScreen);
  549.       if (FindTask(NULL) == IconTask)
  550.          UnLinkScreen(theScreen);
  551.         else
  552.          SendIconMessage(WI_REMSCREEN,NULL,theScreen,NULL);
  553.       CloseIconWindow(theScreen);
  554.       aOldCloseScreen(oldScreen);
  555.       FREESTRUCT(wScreen,theScreen);
  556.    } else {
  557.       Permit();
  558.       aOldCloseScreen(oldScreen);
  559.    }
  560. }
  561.  
  562.  
  563. /*
  564.  *  cSetWindowTitles()
  565.  *
  566.  *  If a window was specified and it is getting a new title
  567.  *     Look for the window's icon
  568.  *     If found, and if the icon has a gadget (ie, it is iconified)
  569.  *       Set the icon's title and center it
  570.  *       Tell wIconify to update the screen
  571.  */
  572.  
  573. void cSetWindowTitles(theWindow,wTitle,sTitle)
  574. struct Window *theWindow;
  575. UBYTE *wTitle,*sTitle;
  576. {
  577.    WICONREF *theIcon;
  578.    WSCREEN *theScreen;
  579.  
  580.    if (theWindow && wTitle != (UBYTE *)-ONE)
  581.    {
  582.       Forbid();
  583.       theIcon = FindIcon(theWindow,&theScreen);
  584.       if (theIcon && theIcon->Gadget)
  585.       {
  586.          theIcon->Gadget->IText.IText = (wTitle)? wTitle: "[No Title]";
  587.          theIcon->Gadget->IText.LeftEdge =
  588.             (((struct Image *)(theIcon->Gadget->Gadget.GadgetRender))->Width -
  589.                IntuiTextLength(&theIcon->Gadget->IText)) / 2;
  590.          SendIconMessage(WI_REDRAW,NULL,theIcon->Screen,NULL);
  591.       }
  592.       Permit();
  593.    }
  594. }
  595.  
  596.  
  597. /*
  598.  *  cWindowToFront()
  599.  *
  600.  *  If a window was specified and it is a BACKDROP window
  601.  *    If the current task is not the wIconify handler process
  602.  *      Find the icon for this window
  603.  *      If it was found and it is iconified, or if its screen was found
  604.  *        and the window is the wIconify backdrop window, don't allow the
  605.  *        window to be moved
  606.  *  Return TRUE if the window can be moved, FLASE otherwise
  607.  */
  608.  
  609. int cWindowToFront(theWindow)
  610. struct Window *theWindow;
  611. {
  612.    int MoveIt = TRUE;
  613.    WICONREF *theIcon;
  614.    WSCREEN *theScreen;
  615.  
  616.    if (theWindow && (theWindow->Flags & BACKDROP))
  617.    {
  618.       if (FindTask(NULL) != IconTask)
  619.       {
  620.          theIcon = FindIcon(theWindow,&theScreen);
  621.          if ((theIcon && (theIcon->Icon.Flags && WI_ICONIFIED)) ||
  622.              (theScreen && theScreen->BackDrop == theWindow)) MoveIt = FALSE;
  623.       }
  624.    }
  625.    return(MoveIt);
  626. }
  627.  
  628. /*
  629.  *  cWindowToBack()
  630.  *
  631.  *  If a window was specified and it is a BACKDROP window
  632.  *    If the current task is not the wIconify handler process
  633.  *      Find the icon for this window
  634.  *      If it was found and it is iconified, or if its screen was found
  635.  *        and the window is the wIconify backdrop window, don't allow the
  636.  *        window to be moved
  637.  *      Otherwise, the window is a BACKDROP window that is being
  638.  *        sent to the back, so it will fall behind the wIconify window
  639.  *        were the user will not be able to get at it, so iconify it
  640.  *        so it can be retrieved.
  641.  *  Return TRUE if the window can be moved, FLASE otherwise
  642.  */
  643.  
  644. int cWindowToBack(theWindow)
  645. struct Window *theWindow;
  646. {
  647.    int MoveIt = TRUE;
  648.    WICONREF *theIcon;
  649.    WSCREEN *theScreen;
  650.  
  651.    if (theWindow && (theWindow->Flags & BACKDROP))
  652.    {
  653.       if (FindTask(NULL) != IconTask)
  654.       {
  655.          theIcon = FindIcon(theWindow,&theScreen);
  656.          if ((theIcon && (theIcon->Icon.Flags & WI_ICONIFIED)) ||
  657.              (theScreen && theScreen->BackDrop == theWindow)) MoveIt = FALSE;
  658.            else SendIconMessage(WI_ICONIFY,theWindow,NULL,NULL);
  659.       }
  660.    }
  661.    return(MoveIt);
  662. }
  663.  
  664.  
  665. /*
  666.  *  cActivateWindow()
  667.  *
  668.  *  If a window was specified and it is a BACKDROP window
  669.  *    If the current process is not the wIconify process
  670.  *      Find the icon for this window
  671.  *      If found and it is iconified, don't all the window to be activated
  672.  *  Return TRUE if it can be activated, FALSE otherwise
  673.  */
  674.  
  675. int cActivateWindow(theWindow)
  676. struct Window *theWindow;
  677. {
  678.    int Activate = TRUE;
  679.    WICONREF *theIcon;
  680.    WSCREEN *theScreen;
  681.  
  682.    if (theWindow && (theWindow->Flags & BACKDROP))
  683.    {
  684.       if (FindTask(NULL) != IconTask)
  685.       {
  686.          theIcon = FindIcon(theWindow,&theScreen);
  687.          if (theIcon && (theIcon->Icon.Flags & WI_ICONIFIED)) Activate = FALSE;
  688.       }
  689.    }
  690.    return(Activate);
  691. }
  692.  
  693.  
  694. /*
  695.  *  cBuildSysRequest()
  696.  *
  697.  *  If wIconify is stil running
  698.  *    If a window was not specified
  699.  *      Get the process that is calling BuildSysRequest()
  700.  *      If it is really a process and it has an error window, use it
  701.  *      If there is still no window
  702.  *        Get the screen and bring-to-front flag as for normal windows
  703.  *        If it is for a different screen, use it's backdrop window
  704.  *    If we have a window to work with
  705.  *      If we don't already have a screen, get it
  706.  *      If the screen is the real WB, ignore it
  707.  *      If we got a screen
  708.  *        Allocate a new wbWindow structure
  709.  *        If this fails, use the original window (ie, don't switch its screen)
  710.  *  Get the system requester on the proper screen
  711.  *  If we actually got a window (not TRUE or FALSE)
  712.  *    If we have a wbWindow for this window, link it in
  713.  *    Bring the screen to the front, if necessary
  714.  *    If the process has a name, use it as the window title
  715.  *      Otherwise use "System Request" as usual
  716.  *  Otherwise, free the wbWindow, if it was allocated
  717.  *  Return the window created by the original BuildSysRequest
  718.  */
  719.  
  720. struct Window *cBuildSysRequest(theWindow,Body,PosText,NegText,Flags,w,h)
  721. struct Window *theWindow;
  722. struct IntuiText *Body,*PosText,*NegText;
  723. ULONG Flags;
  724. long w,h;
  725. {
  726.    extern struct Window *aOldBuildSysRequest();
  727.    struct Process *theProc = NULL;
  728.    struct Window *onWindow = theWindow;
  729.    struct Window *newWindow;
  730.    WBWINDOW *WBWindow = NULL;
  731.    WSCREEN *theScreen = NULL;
  732.    int BringToFront = FALSE;
  733.    char *theTitle;
  734.  
  735.    Forbid();
  736.    if (EndSignal == 0)
  737.    {
  738.       if (onWindow == NULL)
  739.       {
  740.          theProc = (struct Process *)FindTask(NULL);
  741.          if (theProc->pr_Task.tc_Node.ln_Type == NT_PROCESS &&
  742.              theProc->pr_WindowPtr != (APTR)-1)
  743.                  onWindow = (struct Window *)theProc->pr_WindowPtr;
  744.          if (onWindow == NULL)
  745.          {
  746.             theScreen = GetScreen(&BringToFront);
  747.             if (theScreen) onWindow = theScreen->BackDrop;
  748.          }
  749.       }
  750.       if (onWindow)
  751.       {
  752.          if (theScreen == NULL) theScreen = FindScreen(onWindow->WScreen);
  753.          if (theScreen == RealWB) theScreen = NULL;
  754.          if (theScreen)
  755.             if (NEWSTRUCT(wbWindow,WBWindow) == NULL) onWindow = theWindow;
  756.       }
  757.    }
  758.    newWindow = aOldBuildSysRequest(onWindow,Body,PosText,NegText,Flags,w,h);
  759.    if (newWindow && newWindow != (struct Window *)TRUE)
  760.    {
  761.       if (WBWindow)
  762.       {
  763.          WBWindow->Window = newWindow;
  764.          LinkWindow(WBWindow,theScreen);
  765.       }
  766.       if (BringToFront) ScreenToFront(newWindow->WScreen);
  767.       if (theProc && theProc->pr_Task.tc_Node.ln_Name)
  768.          theTitle = theProc->pr_Task.tc_Node.ln_Name;
  769.         else
  770.          theTitle = "System Request";
  771.       SetWindowTitles(newWindow,theTitle,-1L);
  772.    } else {
  773.       if (WBWindow) FREESTRUCT(wbWindow,WBWindow);
  774.    }
  775.    Permit();
  776.    return(newWindow);
  777. }
  778.  
  779.  
  780. /*
  781.  *  cFreeSysRequest()
  782.  *
  783.  *  We are finished with this requester; use the old FreeSysRequest() routine
  784.  *  to remove it from the screen.
  785.  */
  786.  
  787. void cFreeSysRequest(oldWindow)
  788. struct Window *oldWindow;
  789. {
  790.    extern void aOldFreeSysRequest();
  791.  
  792.    FinishWindow(oldWindow,&aOldFreeSysRequest);
  793. }
  794.  
  795.  
  796. /*
  797.  *  cAutoRequest()
  798.  *
  799.  *  Use (the modified) BuildSysRequest() to get a system requester
  800.  *  If we got a window (not TRUE or FALSE)
  801.  *    Get the signal bit for the window's port
  802.  *    While we are not done with the requester
  803.  *      While there are more messages in the port
  804.  *        Get the message info and reply to the message
  805.  *        If the message is one of the positive ones, end with TRUE
  806.  *        If it is one of the negative ones, end with FALSE
  807.  *        If it is a key event and the left amiga key id down
  808.  *          If it is left-amiga-B, cancel the requester
  809.  *          If it is left-amiga-V, retry the requester
  810.  *        If it is a gadget event
  811.  *          If the gadget is the negative one, end with FALSE
  812.  *          If it is the positive one, end with TRUE
  813.  *        If we are not done yet, Wait() for more messages
  814.  *    Finish up the system requester
  815.  *  Otherwise return the answer obtained from BuildSysRequest()
  816.  *  Return the result (TRUE or FALSE)
  817.  */
  818.  
  819. int cAutoRequest(theWindow,Body,PosText,NegText,PFlags,NFlags,w,h)
  820. struct Window *theWindow;
  821. struct IntuiText *Body,*PosText,*NegText;
  822. ULONG PFlags,NFlags;
  823. long w,h;
  824. {
  825.    struct Window *newWindow;
  826.    struct IntuiMessage *theMessage;
  827.    struct Gadget *theGadget;
  828.    ULONG Signal,Class;
  829.    USHORT Code,Qual;
  830.    int Result = NOTDONE;
  831.    extern struct IntuiMessage *GetMsg();
  832.    extern struct Window *BuildSysRequest();
  833.    
  834.    newWindow = BuildSysRequest(theWindow,Body,PosText,NegText,
  835.       GADGETUP|RAWKEY|PFlags|NFlags,w,h);
  836.    if (newWindow && newWindow != (struct Window *)TRUE)
  837.    {
  838.       Signal = (1 << newWindow->UserPort->mp_SigBit);
  839.       while (Result == NOTDONE)
  840.       {
  841.          while (theMessage = GetMsg(newWindow->UserPort))
  842.          {
  843.             Class = theMessage->Class;
  844.             Code  = theMessage->Code;
  845.             Qual  = theMessage->Qualifier;
  846.             theGadget = (struct Gadget *)theMessage->IAddress;
  847.             ReplyMsg(theMessage);
  848.             if (Class & PFlags) Result = TRUE; else
  849.             if (Class & NFlags) Result = FALSE; else
  850.             if (Class == RAWKEY && (Qual & AMIGALEFT))
  851.             {
  852.                if (Code == KEYCODE_B) Result = FALSE; else
  853.                if (Code == KEYCODE_V) Result = TRUE;
  854.             } else if (Class == GADGETUP) {
  855.                if (theGadget->GadgetText == NegText) Result = FALSE; else
  856.                if (theGadget->GadgetText == PosText) Result = TRUE;
  857.             }
  858.          }
  859.          if (Result == NOTDONE) Wait(Signal);
  860.       }
  861.       FreeSysRequest(newWindow);
  862.    } else Result = (int) newWindow;
  863.    return(Result);
  864. }
  865.  
  866.  
  867.  
  868.  
  869. /*
  870.  *  SendIconMessage()
  871.  *
  872.  *  Set up the data for the IconMessage
  873.  *  If the current task is the wIconify process
  874.  *    Call the event routine with the dummy message
  875.  *  Otherwise
  876.  *    Create a reply port
  877.  *    If successful
  878.  *      Set the message reply port
  879.  *      Send the message to the wIconify process
  880.  *      Wait for the reply
  881.  *      Remove the port
  882.  */
  883.  
  884. void SendIconMessage(theAction,theWindow,theScreen,theIcon)
  885. int theAction;
  886. struct Window *theWindow;
  887. WSCREEN *theScreen;
  888. WICONREF *theIcon;
  889. {
  890.    struct wIconMessage theMessage;
  891.    struct MsgPort *thePort;
  892.    extern struct wIconMessage *WaitPort();
  893.    extern struct MsgPort *CreatePort();
  894.    
  895.    theMessage.Window = theWindow;
  896.    theMessage.Icon   = theIcon;
  897.    theMessage.Action = theAction;
  898.    theMessage.Flags  = 0;
  899.    theMessage.Data.wScreen = theScreen;
  900.    if (FindTask(NULL) == IconTask)
  901.    {
  902.       DoIconEvent(&theMessage,TRUE);
  903.    } else {
  904.       thePort = CreatePort(NULL);
  905.       if (thePort)
  906.       {
  907.          theMessage.Message.mn_ReplyPort = thePort;
  908.          theMessage.Message.mn_Length = sizeof(struct wIconMessage);
  909.          PutMsg(wIconPort,&theMessage);
  910.          WaitPort(thePort);
  911.          DeletePort(thePort);
  912.       }
  913.    }
  914. }
  915.  
  916.  
  917. /*
  918.  *  SendIntuiMessage()
  919.  *
  920.  *  If the window has a message port and it accepts this type of message
  921.  *    Allocate a new IntuiMessage structure
  922.  *    If successful
  923.  *      Set the important IntuiMessage fields
  924.  *      Use the wIconify UserPort as the reply port (the wIconify process
  925.  *        will clean up after us)
  926.  *      Send the message to the window
  927.  */
  928.  
  929. void SendIntuiMessage(theClass,theWindow)
  930. ULONG theClass;
  931. struct Window *theWindow;
  932. {
  933.    struct IntuiMessage *theMessage;
  934.  
  935.    if (theWindow && theWindow->UserPort && (theWindow->IDCMPFlags & theClass))
  936.    {
  937.       if (NEWSTRUCT(IntuiMessage,theMessage))
  938.       {
  939.          theMessage->Class = theClass;
  940.          theMessage->Qualifier = 0;
  941.          theMessage->Code = 0;
  942.          theMessage->MouseX = theMessage->MouseY = 0;
  943.          theMessage->IAddress = NULL;
  944.          theMessage->IDCMPWindow = theWindow;
  945.          theMessage->SpecialLink = NULL;
  946.          theMessage->ExecMessage.mn_ReplyPort = wUserPort;
  947.          theMessage->ExecMessage.mn_Length = sizeof(struct IntuiMessage);
  948.          PutMsg(theWindow->UserPort,theMessage);
  949.       }
  950.    }
  951. }
  952.